﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Globalization;
using System.Web.UI.HtmlControls;
using System.Drawing;
using SocialNetwork;
using SocialNetwork.Facebook;


[assembly: WebResource(FacebookLike.FACEBOOK_ICON, "image/bmp")]

namespace SocialNetwork
{
    namespace Facebook
    {
        #region Enums
        public enum LayoutOption
        {
            /// <summary>
            /// displays social text to the right of the button and friends' profile photos below. Minimum width: 225 pixels. 
            /// Default width: 450 pixels. Height: 35 pixels (without photos) or 80 pixels (with photos).
            /// </summary>
            Standard,
            /// <summary>
            /// displays the total number of likes to the right of the button. 
            /// Minimum width: 90 pixels. Default width: 90 pixels. Height: 20 pixels. 
            /// </summary>
            ButtonCount,
            /// <summary>
            /// displays the total number of likes above the button. 
            /// Minimum width: 55 pixels. Default width: 55 pixels. Height: 65 pixels.
            /// </summary>
            BoxCount
        }

        public enum Verbs
        {
            Like,
            Recommend
        }

        public enum Fonts
        {
            Arial,
            LucidaGrande,
            SegoeUi,
            Tahoma,
            TrebuchetMs,
            Verdana
        }

        public enum ColorScheme
        {
            Light,
            Dark
        }

        public enum Implementations
        {
            IFrame,
            XFBML
        }
        #endregion

        [DefaultEvent("Liked")]
        [ToolboxData(@"<{0}:FacebookLike runat=""server""></{0}:FacebookLike>")]
        [ToolboxBitmap(typeof(FacebookLike), FacebookLike.FACEBOOK_ICON)]
        public class FacebookLike : SocialNetworkControl
        {
            public const string FACEBOOK_ICON = "SocialNetwork.Images.Like.bmp";

            #region Properties
            /// <summary>
            /// the URL to like
            /// </summary>
            [DefaultValue("")]
            [Description("the URL to like")]
            [Category("SocialNetwork")]
            public string Href { get; set; }

            [DefaultValue(true)]
            [Category("SocialNetwork")]
            public bool UseCurrentPage
            {
                get
                {
                    return GetData<bool>("UseCurrentPage", true);
                }
                set
                {
                    ViewState["UseCurrentPage"] = value;
                }
            }

            /// <summary>
            /// there are three options
            /// </summary>
            [DefaultValue(LayoutOption.Standard)]
            [Description("there are three options")]
            [Category("SocialNetwork")]
            public LayoutOption Layout { get; set; }

            /// <summary>
            /// specifies whether to display profile photos below the button (standard layout only)
            /// </summary>
            [Description("specifies whether to display profile photos below the button (standard layout only)")]
            [DefaultValue(false)]
            [Category("SocialNetwork")]
            public bool ShowFaces { get; set; }

            /// <summary>
            /// the width of the Like button.
            /// </summary>
            [Description("the width of the Like button.")]
            [Category("SocialNetwork")]
            [DefaultValue(0)]
            public Unit FacebookWidth { get; set; }

            /// <summary>
            /// the verb to display on the button. Options: 'like', 'recommend
            /// </summary>
            [Description("the verb to display on the button. Options: 'like', 'recommend'")]
            [Category("SocialNetwork")]
            [DefaultValue(Verbs.Like)]
            public Verbs Action { get; set; }

            /// <summary>
            /// the font to display in the button
            /// </summary>
            [Description("the font to display in the button")]
            [Category("SocialNetwork")]
            [DefaultValue(Fonts.Arial)]
            public Fonts FacebookFont { get; set; }

            /// <summary>
            /// the color scheme for the like button
            /// </summary>
            [Description("the color scheme for the like button")]
            [DefaultValue(ColorScheme.Light)]
            [Category("SocialNetwork")]
            public ColorScheme Scheme { get; set; }

            /// <summary>
            /// The XFBML dynamically re-sizes its height according to whether there are profile pictures to display, 
            /// gives you the ability (through the Javascript library) to listen for like events so that you know in real time when a user clicks the Like button, 
            /// and it always gives the user the ability to add an optional comment to the like. If users do add a comment,
            /// the story published back to Facebook is given more prominence
            /// </summary>
            [Description("The XFBML dynamically re-sizes its height according to whether there are profile pictures to display, gives you the ability (through the Javascript library) to listen for like events so that you know in real time when a user clicks the Like button, and it always gives the user the ability to add an optional comment to the like. If users do add a comment, the story published back to Facebook is given more prominence")]
            [DefaultValue(Implementations.IFrame)]
            [Category("SocialNetwork")]
            public Implementations Mode { get; set; }

            /// <summary>
            /// display the Like button in different languages
            /// </summary>
            [Description("display the Like button in different languages")]
            [Category("SocialNetwork")]
            public CultureInfo Culture { get; set; }

            #endregion

            #region Render
            protected override void RenderContents(HtmlTextWriter output)
            {
                if (!DesignMode)
                {
                    ValidateValues();

                    switch (Mode)
                    {
                        case Implementations.IFrame:
                            RenderIfrarme(output);
                            break;
                        case Implementations.XFBML:
                            RenderXFBML(output);
                            break;
                    }
                }
                else
                {
                    RenderDesignMode(output);
                }
            }

            private void RenderDesignMode(HtmlTextWriter output)
            {
                output.AddAttribute(HtmlTextWriterAttribute.Width, GetWidth());
                output.AddAttribute(HtmlTextWriterAttribute.Height, GetHeight());
                output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, "silver");
                output.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "solid");
                output.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "1px");
                output.RenderBeginTag(HtmlTextWriterTag.Table);
                output.RenderBeginTag(HtmlTextWriterTag.Tr);

                output.RenderBeginTag(HtmlTextWriterTag.Td);
                output.AddAttribute(HtmlTextWriterAttribute.Src, Page.ClientScript.GetWebResourceUrl(typeof(FacebookLike), FacebookLike.FACEBOOK_ICON));
                output.RenderBeginTag(HtmlTextWriterTag.Img);
                output.RenderEndTag(); // img
                output.RenderEndTag(); // td
                output.RenderEndTag(); //tr
                output.RenderEndTag(); // table
            }

            #region XFBML
            private void RenderXFBML(HtmlTextWriter output)
            {
                RenderXFBMLSrc(output);
                RenderXFBMLAttributes(output);
            }

            private void RenderXFBMLAttributes(HtmlTextWriter output)
            {
                output.AddAttribute("href", GetHref());
                output.AddAttribute("layout", GetLayout());
                output.AddAttribute("action", GetAction());
                output.AddAttribute("font", GetFont());
                output.AddAttribute("colorscheme", GetColorScheme());
                output.AddAttribute("show_faces", ShowFaces.ToString().ToLower());
                output.RenderBeginTag("fb:like");
                output.RenderEndTag();
            }

            private void RenderXFBMLSrc(HtmlTextWriter output)
            {
                output.AddAttribute("src", string.Format("http://connect.facebook.net/{0}/all.js#xfbml=1", GetCulture()));
                output.RenderBeginTag(HtmlTextWriterTag.Script);
                output.RenderEndTag();
            }
            #endregion

            #region IFrame
            private void RenderIfrarme(HtmlTextWriter output)
            {
                RenderIFrameAttributes(output);
                RenderIFrameStyle(output);

                output.RenderBeginTag("iframe");
                output.RenderEndTag();
            }

            private void RenderIFrameStyle(HtmlTextWriter output)
            {
                output.AddStyleAttribute("border", "none");
                output.AddStyleAttribute("overflow", "hidden");
                output.AddStyleAttribute("width", GetWidth());
                output.AddStyleAttribute("height", GetHeight());
            }

            private void RenderIFrameAttributes(HtmlTextWriter output)
            {
                string src = GetSrc();

                output.AddAttribute("src", src);
                output.AddAttribute("scrolling", "no");
                output.AddAttribute("frameborder", "0");
                output.AddAttribute("allowTransparency", "true");
            }
            #endregion
            #endregion

            #region Get Parameters
            private string GetSrc()
            {
                string url = "http://www.facebook.com/plugins/like.php?href=";
                string src = string.Format("{0}{1}&layout={2}&show_faces={3}&width={4}&action={5}&font={6}&colorscheme={7}&height={8}&{9}",
                        url,
                        GetHref(),
                        GetLayout(),
                        ShowFaces.ToString().ToLower(),
                        GetWidth(),
                        GetAction(),
                        GetFont(),
                        GetColorScheme(),
                        GetHeight(),
                        GetCulture());
                return src;
            }

            private string GetCulture()
            {
                if (Mode == Implementations.IFrame)
                {
                    if (Culture == null)
                        return string.Empty;

                    return string.Format("locale={0}", Culture.Name.Replace("-", "_"));
                }

                if (Culture == null)
                {
                    return "en_US";
                }

                return Culture.Name.Replace("-", "_");
            }

            private string GetHeight()
            {
                switch (Layout)
                {
                    case LayoutOption.Standard:
                        {
                            if (ShowFaces)
                                return "80";
                            return "25";
                        }
                    case LayoutOption.ButtonCount: return "20";
                    case LayoutOption.BoxCount: return "65";
                    default: return string.Empty;
                }
            }

            private string GetColorScheme()
            {
                switch (Scheme)
                {
                    case ColorScheme.Light: return "light";
                    case ColorScheme.Dark: return "dark";
                    default: return string.Empty;
                }
            }

            private string GetFont()
            {
                switch (FacebookFont)
                {
                    case Fonts.Arial: return "arial";
                    case Fonts.LucidaGrande: return "lucida grande";
                    case Fonts.SegoeUi: return "segoe ui";
                    case Fonts.Tahoma: return "tahoma";
                    case Fonts.TrebuchetMs: return "trebuchet ms";
                    case Fonts.Verdana: return "verdana";
                    default: return string.Empty;
                }
            }

            private string GetAction()
            {
                switch (Action)
                {
                    case Verbs.Like: return "like";
                    case Verbs.Recommend: return "recommend";
                    default: return string.Empty;
                }
            }

            private string GetWidth()
            {
                if (!FacebookWidth.IsEmpty)
                    return FacebookWidth.ToString();

                switch (Layout)
                {
                    case LayoutOption.Standard: return "450";
                    case LayoutOption.ButtonCount: return "90";
                    case LayoutOption.BoxCount: return "55";
                    default: return string.Empty;
                }
            }

            private string GetLayout()
            {
                switch (Layout)
                {
                    case LayoutOption.Standard: return "standard";
                    case LayoutOption.ButtonCount: return "button_count";
                    case LayoutOption.BoxCount: return "box_count";
                    default: return "standard";
                }
            }

            private string GetHref()
            {
                if (UseCurrentPage && !DesignMode)
                {
                    return HttpContext.Current.Request.Url.ToString();
                }

                return Href;
            }
            #endregion

            #region Validation
            private void ValidateValues()
            {
                ValidateShowFaces();
                ValidateWidth();
                ValidateHref();
            }

            private void ValidateHref()
            {
                if (UseCurrentPage && !string.IsNullOrEmpty(Href))
                {
                    throw new Exception("Href cannot be set if UseCurrentPage is true");
                }

                if (!UseCurrentPage && string.IsNullOrEmpty(Href))
                {
                    throw new Exception("Href cannot be empty if UseCurrentPage is false");
                }
            }

            private void ValidateWidth()
            {
                if (!FacebookWidth.IsEmpty)
                {
                    if (Layout == LayoutOption.Standard && FacebookWidth.Value < 225)
                    {
                        throw new Exception("minimum width in Stantart layout can be 225");
                    }
                    else if (Layout == LayoutOption.ButtonCount && FacebookWidth.Value < 90)
                    {
                        throw new Exception("minimum width in Button_Count layout can be 90");
                    }
                    else if (Layout == LayoutOption.BoxCount && FacebookWidth.Value < 55)
                    {
                        throw new Exception("minimum width in Box_Count layout can be 55");
                    }
                }
            }

            private void ValidateShowFaces()
            {
                if (Layout != LayoutOption.Standard && ShowFaces)
                {
                    throw new Exception("ShowFace can be true just if Layout equal to LayoutOption.Standard");
                }
            }

            #endregion

            
        }
    }
}
